package com.common;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.util.Enumeration;

import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.mozilla.universalchardet.UniversalDetector;

public class FileReadAndWriteORConvert {
	private final static Logger log=Logger.getLogger(FileReadAndWriteORConvert.class);
	
	public static void main(String[] args) {
		FileReadAndWriteORConvert fs  = new FileReadAndWriteORConvert(); 
		String filePath = "E:\\0502\\一键导入的简历\\中国人才热线\\测试乱码文件";
		String content = fs.getContent(filePath);
		System.out.println(content);
//		
//		String fileName = "E:\\0502\\一键导入的简历\\中国人才热线\\测试乱码文件\\14598.htm";
//		fs.readFileByLine(fileName);
		
	}
	
	private String fileSuffix = ".html,.htm,.mht";
	
	public String getContent(String filePath){
		File file=new File(filePath);
		if(!file.exists() || !file.isDirectory()){
			log.error("导入简历 "+filePath+" 目录不存在");
			return "";
		}
		//过滤出文件
		File [] uploadFiles=file.listFiles(new HtmlFilenameFilter());
		String content = "";
		//迭代每一个文件进行导入
		for (File uploadFile : uploadFiles) {
			if (uploadFile.exists() && uploadFile.isFile()) {
				//根据不同类型得到文件html内容
				content = getHtmlContent(uploadFile);
			}
		}
		return content;
	}
	
	/**
	 * 根据不同类型得到文件html内容
	 * @param file
	 * @return
	 */
	private static String getHtmlContent(File file){
		String nameSuffix=file.getName().substring(file.getName().lastIndexOf("."),file.getName().length());
		if(".mht".equalsIgnoreCase(nameSuffix)){
			return FileReadAndWriteORConvert.mhtToHtml(file);
		}else{
			return FileReadAndWriteORConvert.readFile(file);
		}
	}
	
	/**
     * 将 mht文件转换成 html文件
     * @param s_SrcMht
     * @param s_DescHtml
     */
    public static String mhtToHtml(File file) {
    	InputStream fis =null;
    	try {  
    		fis = new FileInputStream(file);
    		Session mailSession = Session.getDefaultInstance(System.getProperties(), null);
    		MimeMessage msg = new MimeMessage(mailSession, fis);
    		Object content = msg.getContent();
    		if (content instanceof Multipart){  
    			MimeMultipart mp = (MimeMultipart)content;  
    			MimeBodyPart bp1 = (MimeBodyPart)mp.getBodyPart(0);
    			
    			//获取mht文件内容代码的编码
    			String strEncodng = getEncoding(bp1);
    			
    			//获取mht文件的内容
    			String strText = getHtmlText(bp1, strEncodng);  
    			if (strText == null)  
    				return "";
    			return strText;
    		}  
    	} catch (Exception e) {  
    		log.error(e);
    	} finally{  
    		try {  
    		if (fis != null)  
    			fis.close();  
    		} catch (Exception e) {  
    			log.info(e);
    		} 
    	}  
    	return "";  
    }
    
    /**
     * 获取mht文件中的内容代码
     * @param bp
     * @param strEncoding 该mht文件的编码
     * @return
     */
    private static String getHtmlText(MimeBodyPart bp, String strEncoding) {  
    	InputStream textStream = null;  
    	BufferedInputStream buff = null;  
    	BufferedReader br = null;  
    	Reader r = null;  
    	try {  
    		textStream = bp.getInputStream();  
    		buff = new BufferedInputStream(textStream);  
    		r = new InputStreamReader(buff, strEncoding); 
    		br = new BufferedReader(r);  
    		StringBuffer strHtml = new StringBuffer("");  
    		String strLine = null;  
    		while ((strLine = br.readLine()) != null) {  
    			strHtml.append(strLine + "\r\n");  
    		}  
    		br.close();  
    		r.close();  
    		textStream.close();  
    		return strHtml.toString();  
    	} catch (Exception e) {  
    	e.printStackTrace();  
    	} finally{
    		try{  
    			if (br != null)  
    			br.close();  
    			if (buff != null)  
    			buff.close();  
    			if (textStream != null)  
    			textStream.close();  
    		}catch(Exception e){  
    		}  
    	}  
    	return null;  
    }
    
    /**
     * 获取mht网页文件中内容代码的编码
     * @param bp
     * @return
     */
    private static String getEncoding(MimeBodyPart bp) {
    	if(bp==null){
    		return null;
    	}
    	try {  
    		Enumeration list = bp.getAllHeaders();  
    		while (list.hasMoreElements()) {  
    			javax.mail.Header head = (javax.mail.Header)list.nextElement();  
    			if (head.getName().compareToIgnoreCase("Content-Type") == 0) {  
    				String strType = head.getValue();  
    				int pos = strType.indexOf("charset=");  
    				if (pos>=0) {  
    					String strEncoding = strType.substring(pos + 8, strType.length());  
    					if(strEncoding.startsWith("\"") || strEncoding.startsWith("\'")){
    						strEncoding = strEncoding.substring(1 , strEncoding.length());
    					}
    					if(strEncoding.endsWith("\"") || strEncoding.endsWith("\'")){
    						strEncoding = strEncoding.substring(0 , strEncoding.length()-1);
    					}
    					if (strEncoding.toLowerCase().compareTo("gb2312") == 0) {  
    						strEncoding = "gbk";  
    					}  
    					return strEncoding;  
    				}  
    			}
    		}  
    	} catch (MessagingException e) {  
    		e.printStackTrace();  
    	}
    	return "gbk"; 
    }
    
    /**
	 * 按行读取文件
	 * @param file
	 * @return
	 */
	public static  String readFile(File file){
		FileInputStream ism = null;
		InputStreamReader isr = null;
		BufferedReader bs =null;
		try {
			String encode=getEncoding(file);
			
			ism = new FileInputStream(file);
			
			isr = new InputStreamReader(ism,encode);
			
			bs = new BufferedReader(isr);
			String line;
			StringBuffer content = new StringBuffer();
			while ((line=bs.readLine()) != null) {
				content.append(line).append("\n");
			}
//			int index = content.toString().indexOf("</HTML>");
//			return content.toString().substring(0,index+7);
			return content.toString();
		} catch (FileNotFoundException e) {
			log.error(e);
		} catch (IOException e) {
			log.error(e);
		} finally{			
			try {
				bs.close();
				isr.close();
				ism.close();
			} catch (Exception e) {
				log.error(e);
			}
		}
		return null;
	}
	
	/**
	 * 得到文件编码
	 *(如果无法确认默认为utf-8)
	 * @param file
	 * @return
	 */
    public static  String getEncoding(File file) {  
    	FileInputStream ism=null;
    	String encoding ="utf-8";
    	//mozilla公司出的一个可以探测网页编码的包juniversalchardet-1.0.3.jar，很快很实用
		UniversalDetector detector = new UniversalDetector(null);
		try {
			ism = new FileInputStream(file);
			byte[] buf = new byte[4096];
			int nread;
			while ((nread = ism.read(buf)) > 0 && !detector.isDone()) {
				detector.handleData(buf, 0, nread);
			}
			detector.dataEnd();
			 encoding = detector.getDetectedCharset();
		}  catch (Exception e) {
			log.error(e);
		}finally{
			try {
				detector.reset();
				ism.close();
			} catch (Exception e) {
				log.error(e);
			}
		}
       return encoding != null ? encoding :"utf-8";
    }  
	
	/**
	 * 文件过滤器
	 * @author james.deng
	 *
	 */
	private class HtmlFilenameFilter implements FilenameFilter{
		public boolean accept(File file, String name) {
			if(StringUtils.isNotBlank(name) && name.lastIndexOf(".")>=0 && StringUtils.isNotBlank(fileSuffix)){
				String [] suffixs=fileSuffix.split(",");
				for (String suffix : suffixs) {
					String nameSuffix=name.substring(name.lastIndexOf("."),name.length());
					if(suffix.equalsIgnoreCase(nameSuffix)){
						return true;
					}
				}
			}
			return false;
		}
	}
	
	/**
	 * <按字节读取文件内容>
	 * <功能详细描述>
	 * @param fileName [参数说明]
	 * 
	 * @return void [返回类型说明]
	 * @exception throws [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public void readFileByByte(String fileName){
		File file = new File(fileName);
        InputStream in = null;
        try {
            System.out.println("以字节为单位读取文件内容，一次读一个字节：");
            // 一次读一个字节
            in = new FileInputStream(file);
            int tempbyte;
            while ((tempbyte = in.read()) != -1) {
                System.out.write(tempbyte);
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        try {
            System.out.println("以字节为单位读取文件内容，一次读多个字节：");
            //一次读多个字节
            byte[] tempbytes = new byte[100];
            int byteread = 0;
            in = new FileInputStream(fileName);
            //读入多个字节到字节数组中，byteread为一次读入的字节数
            while ((byteread = in.read(tempbytes)) != -1) {
                System.out.write(tempbytes, 0, byteread);
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e1) {
                }
            }
        }
	}
	
	/**
	 * <按字符读取文件内容>
	 * <功能详细描述>
	 * @param fileName [参数说明]
	 * 
	 * @return void [返回类型说明]
	 * @exception throws [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public void readFileByChar(String fileName){
		File file = new File(fileName);
        Reader reader = null;
        try {
            System.out.println("以字符为单位读取文件内容，一次读一个字节：");
            // 一次读一个字符
            reader = new InputStreamReader(new FileInputStream(file));
            int tempchar;
            while ((tempchar = reader.read()) != -1) {
                //对于windows下，rn这两个字符在一起时，表示一个换行。
                //但如果这两个字符分开显示时，会换两次行。
                //因此，屏蔽掉r，或者屏蔽n。否则，将会多出很多空行。
                if (((char) tempchar) != 'r') {
                    System.out.print((char) tempchar);
                }
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println("以字符为单位读取文件内容，一次读多个字节：");
            //一次读多个字符
            char[] tempchars = new char[30];
            int charread = 0;
            reader = new InputStreamReader(new FileInputStream(fileName));
            //读入多个字符到字符数组中，charread为一次读取字符数
            while ((charread = reader.read(tempchars)) != -1) {
                //同样屏蔽掉r不显示
                if ((charread == tempchars.length) && (tempchars[tempchars.length - 1] != 'r')) {
                    System.out.print(tempchars);
                } else {
                    for (int i = 0; i < charread; i++) {
                        if (tempchars[i] == 'r') {
                            continue;
                        } else {
                            System.out.print(tempchars[i]);
                        }
                    }
                }
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
	}
	
	/**
	 * <按行读/写文件内容>
	 * <功能详细描述> [参数说明]
	 * 有一点需要注意，当你写文件的时候，为了提高效率，写入的数据会先放入缓冲区，然后写入文件。因此有时候你需要主动调用flush()方法。
	 * @return void [返回类型说明]
	 * @exception throws [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public void readFileByLine(String inputFileName){
//		String inputFileName = "C:\\1.csv";
        FileInputStream csvFis = null;
        FileOutputStream csvfos = null;
        final String vSeparator = System.getProperty("line.separator");
        try {
            // get the encode of file
            String vFileEncode = this.getFileEncoding(inputFileName);
            // read stream
            csvFis = new FileInputStream(inputFileName);
            InputStreamReader inStreamReader = new InputStreamReader(csvFis, vFileEncode);
            BufferedReader reader = new BufferedReader(inStreamReader);
            // write stream
            String outPutFileName = "E:\\0502\\一键导入的简历\\中国人才热线\\测试乱码文件\\9879\\9879test.htm";
            // 接着文件末尾继续写入模式
            //csvfos = new FileOutputStream(outPutFileName, true);
            // 覆盖文件模式
            csvfos = new FileOutputStream(outPutFileName, false);
            OutputStreamWriter outStreamWriter = new OutputStreamWriter(csvfos, vFileEncode);
            BufferedWriter vBufferedWriter = new BufferedWriter(outStreamWriter);
            String tempString = null;
            while ((tempString = reader.readLine()) != null) {
                System.out.println(tempString);
                vBufferedWriter.write(tempString);
                vBufferedWriter.write(vSeparator);
                vBufferedWriter.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (csvFis != null) {
                try {
                    csvFis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (csvfos != null) {
                try {
                    csvfos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

	// 动态取得文件的encode 请参照http://blog.sina.com.cn/s/blog_57769b7b0100tejb.html
	// 需要juniversalchardet-1.0.3.jar
	private String getFileEncoding(String pFileFullPath) {
	    String vResultEncode = "";
	    FileInputStream fis = null;
	    try {
	        fis = new FileInputStream(pFileFullPath);
	        UniversalDetector detector = new UniversalDetector(null);
	        byte[] buf = new byte[4096];
	        int nread;
	        while ((nread = fis.read(buf)) > 0 && !detector.isDone()) {
	            detector.handleData(buf, 0, nread);
	        }
	        detector.dataEnd();
	        String encoding = detector.getDetectedCharset();
	        if (encoding != null) {
	            vResultEncode = encoding;
	        } else {
	            vResultEncode = "SHIFT-JIS";
	        }
	        detector.reset();
	    } catch (IOException e) {
	        e.printStackTrace();
	    } finally {
	        if (fis != null) {
	            try {
	                fis.close();
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	        }
	    }
	    return vResultEncode;
	}
		
}
